﻿using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Net.Http;
using System.Net;
using System;

using NHibernate.Collection.Generic;

using Inovout.Cloud.DataStore.Web.Models;
using Inovout.Cloud.DataStore.Models;
using Inovout.Cloud.DataStore.Services;
using Inovout.Cloud.DataStore.Web.Utility;
using Inovout.Models;

namespace Inovout.Cloud.DataStore.Web.Controllers
{
    public class TableController : DataStoreController
    {
        private ITableService  tableService = null;
        private IPropertyService propertyService = null;

        static TableController()
        {
            AutoMapper.Mapper.CreateMap<TableInfo, Table>();
            AutoMapper.Mapper.CreateMap<Table, TableInfo>();
        }

        public TableController()
        {
            this.tableService = ComponentRegistry.Resolve<ITableService>();
            this.propertyService = ComponentRegistry.Resolve<IPropertyService>();
        }

        /// <summary>
        /// 取得表的定义信息
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        [Route("v1/db/{databaseName}/t/{tableName}")]
        public TableInfo Get(string databaseName, string tableName)
        {
            Table table = GetTable(databaseName, tableName);
            if (table == null)
            {
                return null;
            }

            return BindToViewModel(table);
        }

        /// <summary>
        /// 创建表及表的列
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        [Route("v1/db/{databaseName}/t")]
        public TableInfo Post(string databaseName, TableInfo tableInfo)
        {
            if (String.IsNullOrEmpty(databaseName) || tableInfo == null || string.IsNullOrEmpty(tableInfo.Name))
            {
                return null;
            }

            //如果数据库中已经存在该表，则不重复创建
            Database database = GetDatabase(databaseName);
            if (database == null)
            {
                return null;
            }
            if (database.Tables != null)
            {
                PersistentGenericSet<Table> tables = (PersistentGenericSet<Table>)database.Tables;
                Table table = tables.Where(t => StringUtility.IsEqual(t.Name, tableInfo.Name)).FirstOrDefault();
                if (table != null)
                {
                    return BindToViewModel(table);
                }
            }

            //如果数据库中不存在该表，则创建
            Table tableModel = BindToDomainModel(tableInfo, database);
            return BindToViewModel(tableService.CreateTable(tableModel));
        }

        /// <summary>
        /// 删除表
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="tableName"></param>
        [Route("v1/db/{databaseName}/t/{tableName}")]
        public void Delete(string databaseName, string tableName)
        {
            Database database = GetDatabase(databaseName);
            if (database == null)
            {
                return;
            }

            if (database.Tables != null)
            {
                PersistentGenericSet<Table> tables = (PersistentGenericSet<Table>)database.Tables;
                Table table = tables.Where(t => StringUtility.IsEqual(t.Name, tableName)).FirstOrDefault();
                if (table == null)
                {
                    return;
                }
            }

            this.tableService.DropTable(database, tableName);
        }

        
        /// <summary>
        /// 修改表的列的定义
        /// </summary>
        /// <param name="databaseName"></param>
        /// <param name="tableInfo"></param>
        [Route("v1/db/{databaseName}")]
        public void Put(string databaseName, TableInfo tableInfo)
        {
            Table table = GetTable(databaseName, tableInfo.Name);
            if (table == null)
            {
                return;
            }

            if (tableInfo.Properties != null && tableInfo.Properties.Count() > 0)
            {
                List<Inovout.Cloud.DataStore.Models.Property> properties = new List<Inovout.Cloud.DataStore.Models.Property>();

                Inovout.Cloud.DataStore.Models.Property property = null;
                foreach (Inovout.Cloud.DataStore.Web.Models.PropertyInfo jsonProperty in tableInfo.Properties)
                {
                    property = new DataStore.Models.Property();
                    property.Name = jsonProperty.Name;
                    property.FieldType = (PropertyType)Enum.Parse(typeof(PropertyType), jsonProperty.Type);
                    property.IsPrimaryKey = jsonProperty.IsPrimaryKey;
                    property.Table = table;
                    properties.Add(property);
                }

                propertyService.UpdateProperties(table, properties);
            }
        }

        /// <summary>
        /// 删除所有表
        /// </summary>
        /// <param name="databaseName"></param>
        [Route("v1/db/{databaseName}/t/dropall")]
        [HttpPost]
        [ActionName("Post")]
        public void DropAllTables(string databaseName)
        {
            Database database = GetDatabase(databaseName);
            if (database == null)
            {
                return;
            }

            if (database.Tables == null || database.Tables.Count == 0)
            {
                return;
            }

            tableService.DropAllTables(database);
        }


        /// <summary>
        /// 修改表名
        /// </summary>
        /// <param name="databaseName"></param>
        /// <param name="oldName"></param>
        /// <param name="newName"></param>
        [Route("v1/db/{databaseName}/t/{oldName}/rename/{newName}")]
        [HttpPost]
        [ActionName("Post")]
        public void RenameTable(string databaseName, string oldName, string newName)
        {

            Database database = GetDatabase(databaseName);
            if (database == null)
            {
                return;
            }

            if (database.Tables != null)
            {
                PersistentGenericSet<Table> tables = (PersistentGenericSet<Table>)database.Tables;
                Table table = tables.Where(t => StringUtility.IsEqual(t.Name, oldName)).FirstOrDefault();
                if (table == null)
                {
                    return;
                }
            }

            tableService.ReNameTable(database, oldName, newName);
        }


        [Route("v1/db/{databaseName}/t/dropproperties")]
        [HttpPost]
        [ActionName("Post")]
        public void DropProperties(string databaseName, TableInfo tableInfo)
        {
            Table table = GetTable(databaseName, tableInfo.Name);

            if (tableInfo.Properties != null && tableInfo.Properties.Count() > 0)
            {
                List<Inovout.Cloud.DataStore.Models.Property> properties = new List<Inovout.Cloud.DataStore.Models.Property>();

                Inovout.Cloud.DataStore.Models.Property property = null;
                foreach (Inovout.Cloud.DataStore.Web.Models.PropertyInfo jsonProperty in tableInfo.Properties)
                {
                    property = new DataStore.Models.Property();
                    property.Name = jsonProperty.Name;
                    property.FieldType = (PropertyType)Enum.Parse(typeof(PropertyType), jsonProperty.Type);
                    property.IsPrimaryKey = jsonProperty.IsPrimaryKey;
                    property.Table = table;
                    properties.Add(property);
                }

                propertyService.DropProperties(table, properties);
            }
        }

        /// <summary>
        /// 批量修改或者创建表的列
        /// </summary>
        /// <param name="databaseName"></param>
        /// <param name="tableName"></param>
        [Route("v1/db/{databaseName}/t/saveproperties")]
        [HttpPost]
        [ActionName("Post")]
        public void SaveProperties(string databaseName, TableInfo tableInfo)
        {
            Table table = GetTable(databaseName, tableInfo.Name);

            if (tableInfo.Properties != null && tableInfo.Properties.Count() > 0)
            {
                List<Inovout.Cloud.DataStore.Models.Property> properties = new List<Inovout.Cloud.DataStore.Models.Property>();

                Inovout.Cloud.DataStore.Models.Property property = null;
                foreach (Inovout.Cloud.DataStore.Web.Models.PropertyInfo jsonProperty in tableInfo.Properties)
                {
                    property = new DataStore.Models.Property();
                    property.Name = jsonProperty.Name;
                    property.FieldType = (PropertyType)Enum.Parse(typeof(PropertyType), jsonProperty.Type);
                    property.IsPrimaryKey = jsonProperty.IsPrimaryKey;
                    property.Table = table;
                    properties.Add(property);
                }

                propertyService.SaveProperties(table, properties);
            }
        }

        /// <summary>
        /// 批量创建表的列
        /// </summary>
        /// <param name="databaseName"></param>
        /// <param name="tableInfo"></param>
        [Route("v1/db/{databaseName}/t/createproperties")]
        [HttpPost]
        [ActionName("Post")]
        public void CreateProperties(string databaseName, TableInfo tableInfo)
        {
            Table table = GetTable(databaseName, tableInfo.Name);
            if (table == null)
            {
                return;
            }

            if (tableInfo.Properties != null && tableInfo.Properties.Count() > 0)
            {
                List<Inovout.Cloud.DataStore.Models.Property> properties = new List<Inovout.Cloud.DataStore.Models.Property>();

                Inovout.Cloud.DataStore.Models.Property property = null;
                foreach (Inovout.Cloud.DataStore.Web.Models.PropertyInfo jsonProperty in tableInfo.Properties)
                {
                    property = new DataStore.Models.Property();
                    property.Name = jsonProperty.Name;
                    property.FieldType = (PropertyType)Enum.Parse(typeof(PropertyType), jsonProperty.Type);
                    property.IsPrimaryKey = jsonProperty.IsPrimaryKey;
                    property.Table = table;
                    properties.Add(property);
                }

                propertyService.CreateProperties(properties);
            }
        }

        #region 私有方法
        /// <summary>
        /// 取得Table
        /// </summary>
        /// <param name="projectName">项目名</param>
        /// <param name="tableName">表名</param>
        /// <returns></returns>
        private Table GetTable(string databaseName, string tableName)
        {

            //取得当前项目的数据库
            Database database = GetDatabase(databaseName);
            if (database.Tables == null)
            {
                return null;
            }

            //判断表是否存在
            PersistentGenericSet<Table> tables = (PersistentGenericSet<Table>)database.Tables;
            Table table = tables.Where(t => StringUtility.IsEqual(t.Name, tableName)).FirstOrDefault();
            return table;
        }

        private TableInfo BindToViewModel(Table domainTable)
        {
            TableInfo table = new TableInfo();
            table.Name = domainTable.Name;
            table.CreatedTime = domainTable.CreatedTime;

            if (domainTable.Properties != null && domainTable.Properties.Count() > 0)
            {
                List<Inovout.Cloud.DataStore.Web.Models.PropertyInfo> jsonProperties = new List<Inovout.Cloud.DataStore.Web.Models.PropertyInfo>();
                Inovout.Cloud.DataStore.Web.Models.PropertyInfo jsonProperty = null;
                foreach (Inovout.Cloud.DataStore.Models.Property property in domainTable.Properties)
                {
                    jsonProperty = new Models.PropertyInfo();
                    jsonProperty.Name = property.Name;
                    jsonProperty.Type = property.FieldType.ToString();
                    jsonProperty.IsPrimaryKey = property.IsPrimaryKey;
                    jsonProperties.Add(jsonProperty);
                }

                table.Properties = jsonProperties;
            }

            return table;

        }

        private Table BindToDomainModel(TableInfo viewTable, Database database)
        {
            Table table = new Table();
            table.Name = viewTable.Name;
            table.Database = database;

            if (viewTable.Properties != null && viewTable.Properties.Count() > 0)
            {
                Iesi.Collections.Generic.ISet<Inovout.Cloud.DataStore.Models.Property> properties =
                    new Iesi.Collections.Generic.HashedSet<Inovout.Cloud.DataStore.Models.Property>();

                Inovout.Cloud.DataStore.Models.Property property = null;
                foreach (Inovout.Cloud.DataStore.Web.Models.PropertyInfo jsonProperty in viewTable.Properties)
                {
                    property = new DataStore.Models.Property();
                    property.Name = jsonProperty.Name;
                    property.FieldType = (PropertyType)Enum.Parse(typeof(PropertyType), jsonProperty.Type);
                    property.IsPrimaryKey = jsonProperty.IsPrimaryKey;
                    properties.Add(property);
                }

                table.Properties = properties;
            }
            
            return table;
        }

        #endregion
    }
}
